package com.dehats.getsatisfaction
{
	import com.adobe.serialization.json.JSON;
	import com.dehats.getsatisfaction.vo.*;
	
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import mx.rpc.AsyncToken;
	import mx.rpc.Fault;
	import mx.rpc.IResponder;
	import mx.rpc.Responder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.mxml.HTTPService;

	/**
	 *
	 * <p>Use this class to access the Get Satisfaction API.</p>
	 * 
	 * <p>This class exposes read-only methods of the API.</p> 
	 * 
	 * <p>The results will take the form of ActionScript3 typed objects (see the vo package).</p>
	 *
	 * 
	 * <p>Usage</p>
	 * 
	 * <p>Pass a mx.rpc.IResponder object in its constructor to handle the asynchronous responses, then call the method.</p>
	 * 
	 * <code>var del:GetSatisfactionDelegate = new GetSatisfactionDelegate(new Responder(onGetCompaniesResult, onFault));<br>
				
		del.getAllCompanies(0, pPage);	
		</code>
	 *  
	 * 
	 * <p>Note that you cannot sort AND query in the same method call.</p>
	 * 
	 * <p>Please check the GetSatisfaction API website for more details</p>
	 * 
	 * @see http://developers.getsatisfaction.com/
	 * 
	 * @author davidderaedt
	 * 
	 */
	
	public class GetSatisfactionDelegate
	{

		public static const GS_API_URL:String = "http://api.getsatisfaction.com/";
		public static const GS_URL:String = "http://getsatisfaction.com";
		
		public static var showBusyCursor:Boolean = true ;

   		protected var responder:IResponder;

		/**
		 * 
		 * @param pResponder An mx.rpc.IResponder object to handle the asynchronous responses
		 * 
		 */

		public function GetSatisfactionDelegate(pResponder:IResponder)
		{
			responder = pResponder;						
		}
		

		// Companies

		/**
		 * 
		 * 
		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * 
		 */
		
		public function getAllCompanies(pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="" ):void
		{			
			var operationName:String = "companies.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onCompanyDataLoaded);
		}

		/**
		 * 
		 * 
		 * @param pPersonID The id of the GSPerson object
		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * 
		 */
		 		
		public function getCompaniesByPerson(pPersonID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "people/"+ pPersonID+"/companies.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onCompanyDataLoaded);
		}
		
		/**
		 * 
		 * 
		 * @param pProductID The id of the GSProduct object
		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * 
		 */
		 		
		public function getCompaniesByProduct(pProductID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "products/"+ pProductID+"/companies.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onCompanyDataLoaded);
		}

		// Topics

		/**
		 * 
		 * 
		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */

		public function getAllTopics(pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}		

		/**
		 * 
		 * 
		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */
		public function getFlaggedTopics(pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "flagged/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}
		
		/**
		 * 
		 * 
		 * @param pCompanyID The GSCompany id
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */		
		public function getTopicsByCompany(pCompanyID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "companies/"+ pCompanyID  +"/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}
		
		/**
		 * 
		 * 
		 * @param pPersonID The GSPerson id
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */	
		public function getTopicsByPerson(pPersonID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "people/"+ pPersonID  +"/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}

		/**
		 * 
		 * 
		 * @param pPersonID The GSPerson id
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */	
		public function getTopicsFollowedByPerson(pPersonID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "people/"+ pPersonID  +"/followed/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}
		/**
		 * 
		 * 
		 * @param pProductID The GSProduct id
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */	
		
		public function getTopicsByProduct(pProductID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "products/"+ pProductID  +"/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}

		/**
		 * 
		 * 
		 * @param pTag The tag string
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A CompanySortingOptions value
		 * @param pQuery The search string
		 * @param pStyleFilter A TopicStyles value
		 * 
		 */	
		
		public function getTopicsByTag(pTag:String, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String="", pStyleFilter:String="" ):void
		{			
			var operationName:String = "tags/"+ pTag  +"/topics.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;
			if(pQuery!="") operationName+="&q="+pQuery;			
			if(pStyleFilter!="") operationName+="&style="+pStyleFilter;
			
			performOperation(operationName, onTopicDataLoaded);
		}


		// Products

		/**
		 * 
 		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A ProductSortingOptions value
		 * @param pQuery The search string
		 * 
		 */

		public function getAllProducts( pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "products.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;			
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onProductDataLoaded);
		}		

		/**
		 * 
 		 * @param pCompanyID The id of the GSProduct object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A ProductSortingOptions value
		 * @param pQuery The search string
		 * 
		 */

		public function getProductsByCompany(pCompanyID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "companies/"+ pCompanyID +"/products.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;			
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onProductDataLoaded);
		}		

		/**
		 * 
 		 * @param pPersonID The id of the GSPerson object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A ProductSortingOptions value
		 * @param pQuery The search string
		 * 
		 */
		public function getProductsByPerson(pPersonID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "people/"+ pPersonID +"/products.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;			
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onProductDataLoaded);
		}		
		
		/**
		 * 
 		 * @param pTopicID The id of the GSTopic object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A ProductSortingOptions value
		 * @param pQuery The search string
		 * 
		 */
	
		public function getProductsByTopic(pTopicID:int, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "topic/"+ pTopicID +"/products.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;			
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onProductDataLoaded);
		}		
			
		/**
		 * 
 		 * @param pTag The tag string
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pSort A ProductSortingOptions value
		 * @param pQuery The search string
		 * 
		 */
		public function getProductsByTag(pTag:String, pLimit:int=0, pPage:int=0, pSort:String="", pQuery:String=""  ):void
		{			
			var operationName:String = "tags/"+ pTag +"/products.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pSort!="") operationName+="&sort="+pSort;			
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onProductDataLoaded);
		}	


		//Peoples

		/**
		 * 
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pQuery The search string
		 * 
		 */
		
		public function getAllPeople(pLimit:int=0, pPage:int=0, pQuery:String=""  ):void
		{			
			var operationName:String = "people.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onPersonDataLoaded);
		}

		/**
		 * 
		 * 
		 * @param pCompanyID The id of the GSCompany object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pQuery The search string
		 * 
		 */
				
		public function getPeopleByCompany(pCompanyID:int, pLimit:int=0, pPage:int=0, pQuery:String=""  ):void
		{			
			var operationName:String ="companies/"+ pCompanyID+ "/people.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onPersonDataLoaded);
		}


		/**
		 * 
		 * 
		 * @param pCompanyID The id of the GSCompany object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pQuery The search string
		 * 
		 */
				
		
		public function getEmployeesByCompany(pCompanyID:int, pLimit:int=0, pPage:int=0, pQuery:String=""  ):void
		{			
			var operationName:String ="companies/"+ pCompanyID+ "/employees.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onPersonDataLoaded);
		}


		/**
		 * 
		 * 
		 * @param pTopicID The id of the GSTopic object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pQuery The search string
		 * 
		 */
				
			
		public function getPeopleByTopic(pTopicID:int, pLimit:int=0, pPage:int=0, pQuery:String=""  ):void
		{			
			var operationName:String ="topics/"+ pTopicID+ "/people.json?";
			if(pLimit>0) operationName+="&limit="+ pLimit;
			if(pPage>0) operationName+="&page="+ pPage;
			if(pQuery!="") operationName+="&q="+pQuery;
			
			performOperation(operationName, onPersonDataLoaded);
		}
		
		// Replies

		/**
		 * Warning : undocumented feature
		 * 
		 * @param pTopicID The id of the GSTopic object
  		 * @param pLimit The number of results to return. Max is 30.
		 * @param pPage The result page.
		 * @param pQuery The search string
		 * 
		 */
		
		public function getReplies(pTopicID:int ):void
		{			
			var operationName:String ="topics/"+ pTopicID+ "/replies.json?";
			
			performOperation(operationName, onRepliesDataLoaded);
		}	


		private function performOperation(pOperation:String, pListener:Function):void
		{
			
			var url:String = GS_API_URL+pOperation;
			//trace( url)						
			var httpservice:HTTPService = new HTTPService();
			httpservice.url = url;
			httpservice.resultFormat = "text";
			httpservice.showBusyCursor = showBusyCursor ;
			 
			var token:AsyncToken = httpservice.send();
			token.addResponder(new Responder( pListener, onFault ));
						
		}
		
		private function onFault(pFaultEvt:Event):void
		{
			responder.fault(pFaultEvt);
		}
					
		private function onCompanyDataLoaded(pEvt:ResultEvent):void
		{			
			parseData(pEvt.result.toString(), GSCompany);
		}
		
		private function onPersonDataLoaded(pEvt:ResultEvent):void
		{			
			parseData(pEvt.result.toString(), GSPerson);
		}		
		
		private function onProductDataLoaded(pEvt:ResultEvent):void
		{			
			parseData(pEvt.result.toString(), GSProduct);
		}			
		
		private function onTopicDataLoaded(pEvt:ResultEvent):void
		{			
			parseData(pEvt.result.toString(), GSTopic);
		}		
		private function onRepliesDataLoaded(pEvt:ResultEvent):void
		{			
			parseData(pEvt.result.toString(), GSReply);
		}		
				
		
				
		private function parseData(pData:String, pMappingClass:Class):void
		{
			var mappedList:Array=[];
			if( pData!="")
			{		
				var rawData:Object = JSON.decode(pData);
				var list:Array = rawData.data as Array ;
				mappedList = mapResults(list, pMappingClass) ;
			}

			
			var resultEvent:ResultEvent = new ResultEvent(ResultEvent.RESULT, false, true, mappedList);
			
			responder.result( resultEvent );
		}
		
		private function mapResults(pArray:Array, mappingClass:Class):Array
		{
						
			var tab:Array = [];
			
			for ( var i:int = 0 ; i < pArray.length ; i++)
			{
				var instance:* = mapObject(pArray[i], mappingClass);
				tab.push (instance);
			}
			
			return tab;
		}
		
		private function mapObject(pObject:Object, pClass:Class):*
		{
			var instance:Object = new pClass();
			
			for (var z:String in pObject)
			{
				if(!instance.hasOwnProperty(z))
				{
					trace("unknown property found :"+ z);
				}
				else instance[z] = pObject[z];
			}
			
			return instance;			
		}	

	}
}